package exam.test11.refer;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.util.ArrayList;
import java.util.List;


public class PDXML {

	List<Person> people;

	public PDXML() {
		people = new ArrayList<Person>();
	}

	public List<Person> loadData(String filePath) {
		File file = new File(filePath);
		List<Person> personList = new ArrayList<Person>();

		//create PrintLinkList DocumentBuilder instance: DocumentBuilderFactory
		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
		try {
			//用builderfactory创建builder
			DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
			//创建一个document对象把文件中所有的元素都parse进来
			Document document = documentBuilder.parse(file); //parse file f, it is the root of the document common.tree

			//normalize去除xml文件里的redundant的<>这些东西
			document.getDocumentElement().normalize(); //remove redundancies such as spaces between <  >, line breaks, some white spaces, ...

			//get the common.list of nodes by tag name (all <person> items)
			NodeList nodeList = document.getElementsByTagName("Person"); //以tag name得到node,并存在nodelist里，这里的NodeList类就专门存node的，也就是每一个<Person>包裹的东西就被视作一个node,里面的信息全都在这个node里
			for (int i = 0; i < nodeList.getLength(); i++) {
				Node n = nodeList.item(i); //遍历从nl里取出每一个node
				if (n.getNodeType() == Node.ELEMENT_NODE) {//就是一个检查这个node是否是element的if，如果是那下面就可以直接cast成element
					Element element = (Element) n; //把node强制类型转换成element
					//用getAttributes得到<Person id= "1">括号里面的这个东西
					int id = Integer.parseInt(element.getAttribute("id")); //转换成element之后就可以自由的取出里面的信息了

					//用getElementsByTagName找到这个elements下的sunbchild所包含的属性，也就是<FirstName>Bart</FirstName>
					String firstname = element.getElementsByTagName("FirstName").item(0).getTextContent();
					String lastname = element.getElementsByTagName("LastName").item(0).getTextContent();

					Person p = new Person(id, firstname, lastname); //把导出的这些东西放在一个person对象中
					personList.add(p);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return personList;
	}

	public void saveData(String filePath) {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //创建builderfactory对象
		try {
			//DocumentBuilder obtain PrintLinkList Document from XML (parser)
			DocumentBuilder db = dbf.newDocumentBuilder(); //create PrintLinkList new instance of DocumentBuilder
			Document document = db.newDocument(); //obtain new instance of PrintLinkList DOM document
			//这里创建了一个新的document，与上面的不同，读取的是 Document d = db.parse(f);
			//create the structure of my document
			Element rootElement = document.createElement("People");//<People> 这里虽然是用文件对象d创建的，但是不代表创建之后会自动加入，而是需要手动append
			//创建root
			document.appendChild(rootElement); //append the root to the document

			//把root加入d这个文件里
			for (Person person : people) {
				Element personElement = document.createElement("Person");//<Person>..
				personElement.setAttribute("id", Integer.toString(person.getId()));//<Person id="1">..

				Element firstnameElement = document.createElement("FirstName");//<FirstName> ... </FirstName>
				firstnameElement.appendChild(document.createTextNode(person.getFirstname()));//<FirstName> here goes firstname </FirstName>
				personElement.appendChild(firstnameElement);//<Person id="1"><FirstName> here goes firstname </FirstName></Person>

				//重复之前那一步，把信息写入
				Element lastnameElement = document.createElement("LastName");
				lastnameElement.appendChild(document.createTextNode(person.getLastname()));
				personElement.appendChild(lastnameElement);

				//现在最开始创建的element已经写满了一个单位的信息也就是id,first name和last name,把它append到root里
				rootElement.appendChild(personElement);
			}
			//之前的步骤只是创建了一个xml树而已，想要把这个数写成文件，需要transformer
			Transformer transformer = TransformerFactory.newInstance().newTransformer(); //用transformerfactory创建一个transformer对象

			//set encoding
			transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); //把这个文件的encoding设置成"utf-8"
			//indent the output document
			transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //可以设置成像树一样的，而不是出来就一行

			//create document
			DOMSource source = new DOMSource(document); //Acts as PrintLinkList holder for PrintLinkList transformation Source common.tree in the form of PrintLinkList Document Object Model (DOM) common.tree.
			//创建一个DOMSource对象承接刚刚创建好的document树
			StreamResult result = new StreamResult(new File(filePath));//Acts as PrintLinkList holder for PrintLinkList transformation result, which may be XML,..
			//创建一个StreamResult对象来承接要写入的那个文件，因为还没有把树放进去，所以目前这个文件应该还是空的
			transformer.transform(source, result); //Transform the XML Source to PrintLinkList Result.
			//用transformer把xml树放进文件中
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		PDXML xml = new PDXML();

		xml.people.add(new Person(10, "Lisa", "Simpson"));
		xml.people.add(new Person(11, "Homer", "Simpson"));
		xml.people.add(new Person(12, "Maggie", "Simpson"));

		xml.saveData("resources/people1.xml");

		List<Person> newPeople = xml.loadData("resources/people.xml");
		for (Person p : newPeople) {
			System.out.println(p.toString());
		}
	}
}